﻿using SdmxMl.Common;
using SdmxMl.Helper;
using SdmxMl.Manager;
using SdmxMl.Structure;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Windows.Forms;

namespace SdmxMl.Panels
{
    public partial class DlgReferrer : Form
    {
        SerializableDictionary<string, List<Referrer>> dicoRefCodelists;
        SerializableDictionary<string, List<Referrer>> dicoRefConceptScheme;
        const string REFER_BASE_TAG = "ReferBaseDir";

        public DlgReferrer()
        {
            InitializeComponent();

            if (ConfigurationManager.AppSettings[REFER_BASE_TAG] == null)
                throw new ApplicationException("Reference base directory not specified !");
            string dir = ConfigurationManager.AppSettings[REFER_BASE_TAG].ToString();

            using (new CWaitCursor())
            {
                dicoRefCodelists = CreateBase(SdmxArtefactType.CodeLists, dir, labelCodelist);
                dicoRefConceptScheme = CreateBase(SdmxArtefactType.Concepts, dir, labelConceptScheme);
            }
        }

        private  SerializableDictionary<string, List<Referrer>> CreateBase(SdmxArtefactType arType, string rootDir, Label lbl)
        {
             SerializableDictionary<string, List<Referrer>> dico = new SerializableDictionary<string,List<Referrer>>();
            string destPath = rootDir + arType.ToString() + ReferenceMaker.FILE_ENDER;
            // Check if exist ang get date
            if (File.Exists(destPath))
            {
                TextReader reader = new StreamReader(destPath);
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SerializableDictionary<string, List<Referrer>>));
                dico = (SerializableDictionary<string, List<Referrer>>)serializer.Deserialize(reader);
                lbl.Text += File.GetCreationTime(destPath).ToString(" yyyy-MM-dd");
            }
            else
            {
                lbl.Text += " Undefined";
            }
            return dico;
        }



        #region Update reference to localize

        /// <summary> Update reference to localize </summary>
        /// <param name="tv">Artefact tree view</param>
        public void Update(TreeView tv)
        {
            dataGridViewRef.AutoGenerateColumns = false;
            dataGridViewRef.DataSource = null;

            //If item selected in tree is conceptscheme, concept or code or codelist, prepare urn
            if (tv != null && tv.SelectedNode != null)
            {
                Artefact a = tv.SelectedNode.Tag is Artefact ?
                    tv.SelectedNode.Tag as Artefact :
                    TreeHelper.GetParentArtefact(tv.SelectedNode);

                if (a != null)
                {
                    if (a is CodeListType)
                        textBoxUrn.Text = UrnManager.FullIdToUrn(SdmxArtefactType.CodeLists, a.FullIdent);
                    else if (a is ConceptSchemeType)
                        textBoxUrn.Text = UrnManager.FullIdToUrn(SdmxArtefactType.Concepts, a.FullIdent);
                    else if (a is HierarchicalCodelistType)
                        textBoxUrn.Text = UrnManager.FullIdToUrn(SdmxArtefactType.HierarchicalCodelists, a.FullIdent);
                }

                // Activate search if urn is already given
                if (textBoxUrn.Text.Length > 0)
                    buttonSearchRef_Click(buttonSearchRef, EventArgs.Empty);
            }
        }
        #endregion


        /// <summary> Search references Event </summary>
        /// <param name="sender"></param> <param name="e"></param>
        private void buttonSearchRef_Click(object sender, EventArgs e)
        {
            try
            {
                if (textBoxUrn.Text.Length > 0)
                {
                    UrnParser up = new UrnParser(textBoxUrn.Text);
                    if (up.IsSupported)
                    {
                        if (up.ArType == SdmxArtefactType.CodeLists || up.ArType == SdmxArtefactType.HierarchicalCodelists)
                        {
                            if (dicoRefCodelists.ContainsKey(up.FullIdent))
                            { 
                                dataGridViewRef.DataSource =  GetAsTable(dicoRefCodelists[up.FullIdent]);
                             //   dataGridViewRef.Sort(dataGridViewRef.Columns["ColumnAgency"], System.ComponentModel.ListSortDirection.Ascending);
                            }
                        }
                        else if (up.ArType == SdmxArtefactType.Concepts)
                        {
                            if (dicoRefConceptScheme.ContainsKey(up.FullIdent))
                            {
                                dataGridViewRef.DataSource = GetAsTable(dicoRefConceptScheme[up.FullIdent]);
                            }
                        }
                    }
                    else
                        MessageBox.Show("Invalid reference syntax.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                    MessageBox.Show("Please specifies an URN for ConceptScheme or Codelist", "Caution", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private DataTable GetAsTable(List<Referrer> list)
        {
            DataTable tb = new DataTable();
            foreach (DataGridViewColumn dc in dataGridViewRef.Columns)
            {
                tb.Columns.Add(dc.HeaderText, typeof(string));
            }
            foreach (Referrer refer in list)
            {
                tb.Rows.Add(new object[] { refer.Type, refer.Agency, refer.Id, refer.Version, refer.Urn });
            }
            return tb;
        }

        private void dataGridViewRef_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.RowIndex >= 0)
                buttonNavigate_Click(sender, EventArgs.Empty);
        }

        private void buttonNavigate_Click(object sender, EventArgs e)
        {
            try
            {
                if (dataGridViewRef.SelectedRows != null && dataGridViewRef.SelectedRows.Count > 0)
                {
                    DataGridViewRow fr = dataGridViewRef.SelectedRows[0];
                    DataRowView drv = fr.DataBoundItem as DataRowView;
                    DataRow findRow = drv != null ? drv.Row : null;
                    if (findRow != null)
                    {
                        // If URN try to get it if not already in memory
                        ArtefactRefTyped art = UrnManager.UrnToArtefactRefTyped(findRow["Urn"].ToString());
                        if (art != null)
                        {
                            UrnParser p = new UrnParser(findRow["Urn"].ToString());

                            // If already in memory, navigate otherwhile get from regidtry
                            if (NavigationManager.LocatenavigateProject(art.Type, art.FullIdent, p) == null)
                                NavigationManager.NavigateWithRegistry(art.Type, art.FullIdent, true, p);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


    }
}
